#ifndef MOONLIGHT_OHOS_XCOMPONENTBACKEND_H
#define MOONLIGHT_OHOS_XCOMPONENTBACKEND_H

#include <native_window/external_window.h>
class VideoProcessor;
class AudioProcessor;
class AbstractTouchScreenControlHandler;
class PassThroughController;
class TrackpadEmulator;
class MouseController;
class KeyboardController;
#include <napi/native_api.h>
#include <ace/xcomponent/native_interface_xcomponent.h>
#include <string>


class XComponentBackend final {
public:
    explicit XComponentBackend(std::string_view id, OHNativeWindow *nativeWindow);
    ~XComponentBackend();
private:
    XComponentBackend(const XComponentBackend &) = delete;
    void operator=(const XComponentBackend &) = delete;

public:
    static napi_status doInit(napi_env env, napi_value exports, std::string &xcompId);
private:
    struct XComponentCallbacks {
        static void OnSurfaceCreated(OH_NativeXComponent *comp, void *win);
        static void OnSurfaceChanged(OH_NativeXComponent *comp, void *win);
        static void OnSurfaceDestroyed(OH_NativeXComponent *comp, void *win);
        static void DispatchTouchEvent(OH_NativeXComponent *comp, void *win);
        static inline const OH_NativeXComponent_Callback callbacks = {
            .OnSurfaceCreated = OnSurfaceCreated,
            .OnSurfaceChanged = OnSurfaceChanged,
            .OnSurfaceDestroyed = OnSurfaceDestroyed,
            .DispatchTouchEvent = DispatchTouchEvent,
        };

        static void DispatchMouseEvent(OH_NativeXComponent *comp, void *win);
        static void DispatchHoverEvent(OH_NativeXComponent *comp, bool isHover);
        static inline const OH_NativeXComponent_MouseEvent_Callback mouseEventCallbacks = {
            .DispatchMouseEvent = DispatchMouseEvent,
            .DispatchHoverEvent = DispatchHoverEvent,
        };

        static bool KeyEventCallback(OH_NativeXComponent *comp, void *win);

        static constexpr double scrollValuePerClick = 45;
        static void UIInputAxisEventCallback(OH_NativeXComponent *comp, ArkUI_UIInputEvent *event,
                     ArkUI_UIInputEvent_Type type);

        static constexpr bool DEBUG = false;
    };

public:
    void setTouchHandler(std::unique_ptr<AbstractTouchScreenControlHandler> touchHandler);

private:
    const std::string id;
    OHNativeWindow *const nativeWindow;

    friend VideoProcessor;
    std::unique_ptr<VideoProcessor> videoProcessor;
    friend AudioProcessor;
    std::unique_ptr<AudioProcessor> audioProcessor;

    std::unique_ptr<AbstractTouchScreenControlHandler> touchHandler;
    std::unique_ptr<MouseController> mouseController;
    std::unique_ptr<KeyboardController> keyboardController;

    std::atomic<bool> stopFlag = false;

};


#define INIT_XCOMPONENT_SELF_OR_ELSE(otherwise) \
    ENSURE_GSMGR_OR_ELSE(otherwise); \
    auto &self = *GameStreamManager::xcomponentBackend;

#endif //MOONLIGHT_OHOS_XCOMPONENTBACKEND_H
